package open.douban.hashtree;

import java.io.IOException;
import java.util.Random;

import junit.framework.Assert;

import org.junit.BeforeClass;
import org.junit.Test;

import open.douban.hashtree.HashTree.Item;
import open.douban.hashtree.HashTreeMirror.HTStore;

/**
 * To run the test: -Xmx1024m
 */
public class HashTreeMirrorTest {
	static HashTree ht_1 = null;
	static HashTree ht_2 = null;

	static class TreeStore implements HTStore {
		HashTree t = null;

		public TreeStore(HashTree t) {
			this.t = t;
		}

		@Override
		public Object get(int key) throws IOException {
			return t.findItem(key).hash_v;
		}

		@Override
		public void set(int key, Object hashV) throws IOException {
			t.setItem(key, (Integer) hashV, false);
		}

		@Override
		public void set(int key, Object old, Object _new) throws IOException {
			t.setItem(key, (Integer) _new, false);
		}

		@Override
		public String listDir(String path) throws IOException {
			return t.listDir(path);
		}
	}

	@BeforeClass
	public static void setup() throws IOException {
		ht_1 = HashTreeTest.getHashTree(""); // not save, path is blank
		ht_2 = HashTreeTest.getHashTree("");
	}

	private int print = 1000000;

	@Test
	public void testSync() throws IOException, InterruptedException {
		int cnt = 256 * 256 * 256; // 65536 * 16 = 1048576 items
		for (int i = 0; i < cnt; i += 16) {
			// 10% probability miss sync
			if (i % 10 == 0) {
				if (i % print == 0)
					System.out.println("add: " + i);
				int r = new Random().nextInt(4);
				switch (r) {
				case 0:
					ht_1.setItem(i, i, false);
					break;
				case 1:
					ht_2.setItem(i, i, false);
					break;
				case 2:
					ht_1.setItem(i, i - r, false);
					ht_2.setItem(i, i, false);
					break;
				case 3:
					ht_1.setItem(i, i, false);
					ht_2.setItem(i, i - r, false);
					break;
				}
			} else {
				ht_1.setItem(i, i, false);
				ht_2.setItem(i, i, false);
			}
		}

		HashTreeMirror.sync(new TreeStore(ht_1), new TreeStore(ht_2));

		for (int i = 0; i < cnt; i += 16) {
			if (i % print == 0)
				System.out.println("find: " + i);

			Item item = ht_1.findItem(i);
			Assert.assertEquals(item.key, i);
			Assert.assertEquals(item.hash_v, i);

			item = ht_2.findItem(i);
			Assert.assertEquals(item.key, i);
			Assert.assertEquals(item.hash_v, i);
		}
	}
}
